{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "20549885",
   "metadata": {},
   "source": [
    "# 使用 Milvus 和 DeepSeek 构建 RAG\n",
    "\n",
    "DeepSeek 帮助开发者使用高性能语言模型构建和扩展 AI 应用。它提供高效的推理、灵活的 API 以及先进的专家混合 (MoE) 架构，用于强大的推理和检索任务。\n",
    "\n",
    "在本教程中，我们将展示如何使用 Milvus 和 DeepSeek 构建一个检索增强生成 (RAG) 管道。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7394c701",
   "metadata": {},
   "source": [
    "## 准备工作"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "89103a1e",
   "metadata": {},
   "source": [
    "### 依赖与环境"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "9c18d7b4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: openai in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (1.82.0)\n",
      "Requirement already satisfied: requests in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (2.32.3)\n",
      "Requirement already satisfied: tqdm in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (4.67.1)\n",
      "Requirement already satisfied: torch in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (2.7.0)\n",
      "Requirement already satisfied: pymilvus[model] in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (2.5.10)\n",
      "Requirement already satisfied: setuptools>69 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus[model]) (78.1.1)\n",
      "Requirement already satisfied: grpcio<=1.67.1,>=1.49.1 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus[model]) (1.67.1)\n",
      "Requirement already satisfied: protobuf>=3.20.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus[model]) (6.31.0)\n",
      "Requirement already satisfied: python-dotenv<2.0.0,>=1.0.1 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus[model]) (1.1.0)\n",
      "Requirement already satisfied: ujson>=2.0.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus[model]) (5.10.0)\n",
      "Requirement already satisfied: pandas>=1.2.4 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus[model]) (2.2.3)\n",
      "Requirement already satisfied: milvus-lite>=2.4.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus[model]) (2.4.12)\n",
      "Requirement already satisfied: pymilvus.model>=0.3.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus[model]) (0.3.2)\n",
      "Requirement already satisfied: anyio<5,>=3.5.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from openai) (4.9.0)\n",
      "Requirement already satisfied: distro<2,>=1.7.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from openai) (1.9.0)\n",
      "Requirement already satisfied: httpx<1,>=0.23.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from openai) (0.28.1)\n",
      "Requirement already satisfied: jiter<1,>=0.4.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from openai) (0.10.0)\n",
      "Requirement already satisfied: pydantic<3,>=1.9.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from openai) (2.11.4)\n",
      "Requirement already satisfied: sniffio in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from openai) (1.3.1)\n",
      "Requirement already satisfied: typing-extensions<5,>=4.11 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from openai) (4.13.2)\n",
      "Requirement already satisfied: idna>=2.8 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from anyio<5,>=3.5.0->openai) (3.10)\n",
      "Requirement already satisfied: certifi in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from httpx<1,>=0.23.0->openai) (2025.4.26)\n",
      "Requirement already satisfied: httpcore==1.* in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from httpx<1,>=0.23.0->openai) (1.0.9)\n",
      "Requirement already satisfied: h11>=0.16 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.16.0)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pydantic<3,>=1.9.0->openai) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.33.2 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pydantic<3,>=1.9.0->openai) (2.33.2)\n",
      "Requirement already satisfied: typing-inspection>=0.4.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pydantic<3,>=1.9.0->openai) (0.4.0)\n",
      "Requirement already satisfied: charset_normalizer<4,>=2 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from requests) (3.4.2)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from requests) (2.4.0)\n",
      "Requirement already satisfied: filelock in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (3.18.0)\n",
      "Requirement already satisfied: sympy>=1.13.3 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (1.14.0)\n",
      "Requirement already satisfied: networkx in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (3.4.2)\n",
      "Requirement already satisfied: jinja2 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (3.1.6)\n",
      "Requirement already satisfied: fsspec in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (2025.5.0)\n",
      "Requirement already satisfied: nvidia-cuda-nvrtc-cu12==12.6.77 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (12.6.77)\n",
      "Requirement already satisfied: nvidia-cuda-runtime-cu12==12.6.77 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (12.6.77)\n",
      "Requirement already satisfied: nvidia-cuda-cupti-cu12==12.6.80 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (12.6.80)\n",
      "Requirement already satisfied: nvidia-cudnn-cu12==9.5.1.17 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (9.5.1.17)\n",
      "Requirement already satisfied: nvidia-cublas-cu12==12.6.4.1 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (12.6.4.1)\n",
      "Requirement already satisfied: nvidia-cufft-cu12==11.3.0.4 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (11.3.0.4)\n",
      "Requirement already satisfied: nvidia-curand-cu12==10.3.7.77 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (10.3.7.77)\n",
      "Requirement already satisfied: nvidia-cusolver-cu12==11.7.1.2 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (11.7.1.2)\n",
      "Requirement already satisfied: nvidia-cusparse-cu12==12.5.4.2 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (12.5.4.2)\n",
      "Requirement already satisfied: nvidia-cusparselt-cu12==0.6.3 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (0.6.3)\n",
      "Requirement already satisfied: nvidia-nccl-cu12==2.26.2 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (2.26.2)\n",
      "Requirement already satisfied: nvidia-nvtx-cu12==12.6.77 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (12.6.77)\n",
      "Requirement already satisfied: nvidia-nvjitlink-cu12==12.6.85 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (12.6.85)\n",
      "Requirement already satisfied: nvidia-cufile-cu12==1.11.1.6 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (1.11.1.6)\n",
      "Requirement already satisfied: triton==3.3.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from torch) (3.3.0)\n",
      "Requirement already satisfied: numpy>=1.26.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pandas>=1.2.4->pymilvus[model]) (2.2.6)\n",
      "Requirement already satisfied: python-dateutil>=2.8.2 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pandas>=1.2.4->pymilvus[model]) (2.9.0.post0)\n",
      "Requirement already satisfied: pytz>=2020.1 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pandas>=1.2.4->pymilvus[model]) (2025.2)\n",
      "Requirement already satisfied: tzdata>=2022.7 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pandas>=1.2.4->pymilvus[model]) (2025.2)\n",
      "Requirement already satisfied: transformers>=4.36.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus.model>=0.3.0->pymilvus[model]) (4.52.2)\n",
      "Requirement already satisfied: onnxruntime in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus.model>=0.3.0->pymilvus[model]) (1.22.0)\n",
      "Requirement already satisfied: scipy>=1.10.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from pymilvus.model>=0.3.0->pymilvus[model]) (1.15.3)\n",
      "Requirement already satisfied: six>=1.5 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from python-dateutil>=2.8.2->pandas>=1.2.4->pymilvus[model]) (1.17.0)\n",
      "Requirement already satisfied: mpmath<1.4,>=1.1.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from sympy>=1.13.3->torch) (1.3.0)\n",
      "Requirement already satisfied: huggingface-hub<1.0,>=0.30.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from transformers>=4.36.0->pymilvus.model>=0.3.0->pymilvus[model]) (0.31.4)\n",
      "Requirement already satisfied: packaging>=20.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from transformers>=4.36.0->pymilvus.model>=0.3.0->pymilvus[model]) (25.0)\n",
      "Requirement already satisfied: pyyaml>=5.1 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from transformers>=4.36.0->pymilvus.model>=0.3.0->pymilvus[model]) (6.0.2)\n",
      "Requirement already satisfied: regex!=2019.12.17 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from transformers>=4.36.0->pymilvus.model>=0.3.0->pymilvus[model]) (2024.11.6)\n",
      "Requirement already satisfied: tokenizers<0.22,>=0.21 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from transformers>=4.36.0->pymilvus.model>=0.3.0->pymilvus[model]) (0.21.1)\n",
      "Requirement already satisfied: safetensors>=0.4.3 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from transformers>=4.36.0->pymilvus.model>=0.3.0->pymilvus[model]) (0.5.3)\n",
      "Requirement already satisfied: MarkupSafe>=2.0 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from jinja2->torch) (3.0.2)\n",
      "Requirement already satisfied: coloredlogs in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from onnxruntime->pymilvus.model>=0.3.0->pymilvus[model]) (15.0.1)\n",
      "Requirement already satisfied: flatbuffers in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from onnxruntime->pymilvus.model>=0.3.0->pymilvus[model]) (25.2.10)\n",
      "Requirement already satisfied: humanfriendly>=9.1 in /home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages (from coloredlogs->onnxruntime->pymilvus.model>=0.3.0->pymilvus[model]) (10.0)\n"
     ]
    }
   ],
   "source": [
    "!pip install \"pymilvus[model]==2.5.10\" openai==1.82.0 requests==2.32.3 tqdm==4.67.1 torch==2.7.0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1b3c0999-d670-41a9-afbd-d8a020fe1631",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "375ad823",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "# 从环境变量获取 DeepSeek API Key\n",
    "api_key = os.getenv(\"DEEPSEEK_API_KEY\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db44bb26",
   "metadata": {},
   "source": [
    "### 准备数据"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "25f92a95",
   "metadata": {},
   "source": [
    "我们使用 Milvus 文档 2.4.x 中的 FAQ 页面作为我们 RAG 中的私有知识库，这是一个简单 RAG 管道的良好数据源。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a1a8b9e2",
   "metadata": {},
   "source": [
    "下载 zip 文件并将文档解压到 `milvus_docs` 文件夹。\n",
    "\n",
    "**建议在命令行执行下面命令**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "a81fa031",
   "metadata": {},
   "outputs": [],
   "source": [
    "#!wget https://github.com/milvus-io/milvus-docs/releases/download/v2.4.6-preview/milvus_docs_2.4.x_en.zip\n",
    "#!unzip -q milvus_docs_2.4.x_en.zip -d milvus_docs"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1198466",
   "metadata": {},
   "source": [
    "我们从 `milvus_docs/en/faq` 文件夹加载所有 markdown 文件。对于每个文档，我们简单地使用 \"# \" 来分割文件中的内容，这样可以大致分离出 markdown 文件中每个主要部分的内容。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c9035a5f",
   "metadata": {},
   "outputs": [],
   "source": [
    "from glob import glob\n",
    "\n",
    "text_lines = []\n",
    "\n",
    "for file_path in glob(\"milvus_docs/en/faq/*.md\", recursive=True):\n",
    "    with open(file_path, \"r\") as file:\n",
    "        file_text = file.read()\n",
    "\n",
    "    text_lines += file_text.split(\"# \")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "01b73e74-ee7d-4daf-b7db-1c7a10bfc0bf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "72"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(text_lines)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4cc2a0b8",
   "metadata": {},
   "source": [
    "### 准备 LLM 和 Embedding 模型"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19eaff7a",
   "metadata": {},
   "source": [
    "DeepSeek 支持 OpenAI 风格的 API，您可以使用相同的 API 进行微小调整来调用 LLM。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b994eb47",
   "metadata": {},
   "outputs": [],
   "source": [
    "from openai import OpenAI\n",
    "\n",
    "deepseek_client = OpenAI(\n",
    "    api_key=api_key,\n",
    "    base_url=\"https://api.deepseek.com/v1\",  # DeepSeek API 的基地址\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cc5a5e2",
   "metadata": {},
   "source": [
    "定义一个 embedding 模型，使用 `milvus_model` 来生成文本嵌入。我们以 `DefaultEmbeddingFunction` 模型为例，这是一个预训练的轻量级嵌入模型。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "3a94242a",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/django/miniconda3/envs/deepseek/lib/python3.13/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    }
   ],
   "source": [
    "from pymilvus import model as milvus_model\n",
    "\n",
    "embedding_model = milvus_model.DefaultEmbeddingFunction()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93fb1696",
   "metadata": {},
   "source": [
    "生成一个测试嵌入并打印其维度和前几个元素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "88a27567",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "768\n",
      "[-0.04836059  0.07163021 -0.01130063 -0.03789341 -0.03320651 -0.01318453\n",
      " -0.03041721 -0.02269495 -0.02317858 -0.00426026]\n"
     ]
    }
   ],
   "source": [
    "test_embedding = embedding_model.encode_queries([\"This is a test\"])[0]\n",
    "embedding_dim = len(test_embedding)\n",
    "print(embedding_dim)\n",
    "print(test_embedding[:10])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f7683f3a-d9e4-4c8e-9a66-c341911bef6b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-0.02752976  0.0608853   0.00388525 -0.00215193 -0.02774976 -0.0118618\n",
      " -0.04020916 -0.06023417 -0.03813156  0.0100272 ]\n"
     ]
    }
   ],
   "source": [
    "test_embedding_0 = embedding_model.encode_queries([\"That is a test\"])[0]\n",
    "print(test_embedding_0[:10])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a778887",
   "metadata": {},
   "source": [
    "## 将数据加载到 Milvus"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "02b23a24",
   "metadata": {},
   "source": [
    "### 创建 Collection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "95e84b8c",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pymilvus import MilvusClient\n",
    "\n",
    "milvus_client = MilvusClient(uri=\"./milvus_demo.db\")\n",
    "\n",
    "collection_name = \"my_rag_collection\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68648561",
   "metadata": {},
   "source": [
    "关于 `MilvusClient` 的参数：\n",
    "\n",
    "*   将 `uri` 设置为本地文件，例如 `./milvus.db`，是最方便的方法，因为它会自动利用 Milvus Lite 将所有数据存储在此文件中。\n",
    "*   如果您有大规模数据，可以在 Docker 或 Kubernetes 上设置性能更高的 Milvus 服务器。在此设置中，请使用服务器 URI，例如 `http://localhost:19530`，作为您的 `uri`。\n",
    "*   如果您想使用 Zilliz Cloud（Milvus 的完全托管云服务），请调整 `uri` 和 `token`，它们对应 Zilliz Cloud 中的 Public Endpoint 和 Api key。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ce1bf3e",
   "metadata": {},
   "source": [
    "检查 collection 是否已存在，如果存在则删除它。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "aee85c08",
   "metadata": {},
   "outputs": [],
   "source": [
    "if milvus_client.has_collection(collection_name):\n",
    "    milvus_client.drop_collection(collection_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73eb379f",
   "metadata": {},
   "source": [
    "创建一个具有指定参数的新 collection。\n",
    "\n",
    "如果我们不指定任何字段信息，Milvus 将自动创建一个默认的 `id` 字段作为主键，以及一个 `vector` 字段来存储向量数据。一个保留的 JSON 字段用于存储非 schema 定义的字段及其值。\n",
    "\n",
    "`metric_type` (距离度量类型):\n",
    "     作用：定义如何计算向量之间的相似程度。\n",
    "     例如：`IP` (内积) - 值越大通常越相似；`L2` (欧氏距离) - 值越小越相似；`COSINE` (余弦相似度) - 通常转换为距离，值越小越相似。\n",
    "     选择依据：根据你的嵌入模型的特性和期望的相似性定义来选择。\n",
    "\n",
    " `consistency_level` (一致性级别):\n",
    "     作用：定义数据写入后，读取操作能多快看到这些新数据。\n",
    "     例如：\n",
    "         `Strong` (强一致性): 总是读到最新数据，可能稍慢。\n",
    "         `Bounded` (有界过期): 可能读到几秒内旧数据，性能较好 (默认)。\n",
    "         `Session` (会话一致性): 自己写入的自己能立刻读到。\n",
    "         `Eventually` (最终一致性): 最终会读到新数据，但没时间保证，性能最好。\n",
    "     选择依据：在数据实时性要求和系统性能之间做权衡。\n",
    "\n",
    "简单来说：\n",
    " `metric_type`：怎么算相似。\n",
    " `consistency_level`：新数据多久能被读到。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "bd0b2df8",
   "metadata": {},
   "outputs": [],
   "source": [
    "milvus_client.create_collection(\n",
    "    collection_name=collection_name,\n",
    "    dimension=embedding_dim,\n",
    "    metric_type=\"IP\",  # 内积距离\n",
    "    consistency_level=\"Strong\",  # 支持的值为 (`\"Strong\"`, `\"Session\"`, `\"Bounded\"`, `\"Eventually\"`)。更多详情请参见 https://milvus.io/docs/consistency.md#Consistency-Level。\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c15bafb",
   "metadata": {},
   "source": [
    "### 插入数据"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "171d3b35",
   "metadata": {},
   "source": [
    "遍历文本行，创建嵌入，然后将数据插入 Milvus。\n",
    "\n",
    "这里有一个新字段 `text`，它是在 collection schema 中未定义的字段。它将自动添加到保留的 JSON 动态字段中，该字段在高级别上可以被视为普通字段。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "ad077094",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Creating embeddings: 100%|██████████| 72/72 [00:00<00:00, 502479.01it/s]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'insert_count': 72, 'ids': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71], 'cost': 0}"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from tqdm import tqdm\n",
    "\n",
    "data = []\n",
    "\n",
    "doc_embeddings = embedding_model.encode_documents(text_lines)\n",
    "\n",
    "for i, line in enumerate(tqdm(text_lines, desc=\"Creating embeddings\")):\n",
    "    data.append({\"id\": i, \"vector\": doc_embeddings[i], \"text\": line})\n",
    "\n",
    "milvus_client.insert(collection_name=collection_name, data=data)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd971f6b",
   "metadata": {},
   "source": [
    "## 构建 RAG"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "534dc076",
   "metadata": {},
   "source": [
    "### 检索查询数据"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a6fd7e7",
   "metadata": {},
   "source": [
    "我们指定一个关于 Milvus 的常见问题。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "6e2f5c6a",
   "metadata": {},
   "outputs": [],
   "source": [
    "question = \"How is data stored in milvus?\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52401a38",
   "metadata": {},
   "source": [
    "在 collection 中搜索该问题，并检索语义上最匹配的前3个结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "0dd4cbac",
   "metadata": {},
   "outputs": [],
   "source": [
    "search_res = milvus_client.search(\n",
    "    collection_name=collection_name,\n",
    "    data=embedding_model.encode_queries(\n",
    "        [question]\n",
    "    ),  # 将问题转换为嵌入向量\n",
    "    limit=3,  # 返回前3个结果\n",
    "    search_params={\"metric_type\": \"IP\", \"params\": {}},  # 内积距离\n",
    "    output_fields=[\"text\"],  # 返回 text 字段\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ffcce135",
   "metadata": {},
   "source": [
    "让我们看一下查询的搜索结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "6a7f6eb3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[\n",
      "    [\n",
      "        \" Where does Milvus store data?\\n\\nMilvus deals with two types of data, inserted data and metadata. \\n\\nInserted data, including vector data, scalar data, and collection-specific schema, are stored in persistent storage as incremental log. Milvus supports multiple object storage backends, including [MinIO](https://min.io/), [AWS S3](https://aws.amazon.com/s3/?nc1=h_ls), [Google Cloud Storage](https://cloud.google.com/storage?hl=en#object-storage-for-companies-of-all-sizes) (GCS), [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs), [Alibaba Cloud OSS](https://www.alibabacloud.com/product/object-storage-service), and [Tencent Cloud Object Storage](https://www.tencentcloud.com/products/cos) (COS).\\n\\nMetadata are generated within Milvus. Each Milvus module has its own metadata that are stored in etcd.\\n\\n###\",\n",
      "        0.65726637840271\n",
      "    ],\n",
      "    [\n",
      "        \"How does Milvus flush data?\\n\\nMilvus returns success when inserted data are loaded to the message queue. However, the data are not yet flushed to the disk. Then Milvus' data node writes the data in the message queue to persistent storage as incremental logs. If `flush()` is called, the data node is forced to write all data in the message queue to persistent storage immediately.\\n\\n###\",\n",
      "        0.6312143802642822\n",
      "    ],\n",
      "    [\n",
      "        \"How does Milvus handle vector data types and precision?\\n\\nMilvus supports Binary, Float32, Float16, and BFloat16 vector types.\\n\\n- Binary vectors: Store binary data as sequences of 0s and 1s, used in image processing and information retrieval.\\n- Float32 vectors: Default storage with a precision of about 7 decimal digits. Even Float64 values are stored with Float32 precision, leading to potential precision loss upon retrieval.\\n- Float16 and BFloat16 vectors: Offer reduced precision and memory usage. Float16 is suitable for applications with limited bandwidth and storage, while BFloat16 balances range and efficiency, commonly used in deep learning to reduce computational requirements without significantly impacting accuracy.\\n\\n###\",\n",
      "        0.6115782260894775\n",
      "    ]\n",
      "]\n"
     ]
    }
   ],
   "source": [
    "import json\n",
    "\n",
    "retrieved_lines_with_distances = [\n",
    "    (res[\"entity\"][\"text\"], res[\"distance\"]) for res in search_res[0]\n",
    "]\n",
    "print(json.dumps(retrieved_lines_with_distances, indent=4))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ccd4c186",
   "metadata": {},
   "source": [
    "### 使用 LLM 获取 RAG 响应"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4cd1ae3a",
   "metadata": {},
   "source": [
    "将检索到的文档转换为字符串格式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "0676448f",
   "metadata": {},
   "outputs": [],
   "source": [
    "context = \"\\n\".join(\n",
    "    [line_with_distance[0] for line_with_distance in retrieved_lines_with_distances]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "107df42a-b3f7-48a8-b66b-fc82fe3ec174",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\" Where does Milvus store data?\\n\\nMilvus deals with two types of data, inserted data and metadata. \\n\\nInserted data, including vector data, scalar data, and collection-specific schema, are stored in persistent storage as incremental log. Milvus supports multiple object storage backends, including [MinIO](https://min.io/), [AWS S3](https://aws.amazon.com/s3/?nc1=h_ls), [Google Cloud Storage](https://cloud.google.com/storage?hl=en#object-storage-for-companies-of-all-sizes) (GCS), [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs), [Alibaba Cloud OSS](https://www.alibabacloud.com/product/object-storage-service), and [Tencent Cloud Object Storage](https://www.tencentcloud.com/products/cos) (COS).\\n\\nMetadata are generated within Milvus. Each Milvus module has its own metadata that are stored in etcd.\\n\\n###\\nHow does Milvus flush data?\\n\\nMilvus returns success when inserted data are loaded to the message queue. However, the data are not yet flushed to the disk. Then Milvus' data node writes the data in the message queue to persistent storage as incremental logs. If `flush()` is called, the data node is forced to write all data in the message queue to persistent storage immediately.\\n\\n###\\nHow does Milvus handle vector data types and precision?\\n\\nMilvus supports Binary, Float32, Float16, and BFloat16 vector types.\\n\\n- Binary vectors: Store binary data as sequences of 0s and 1s, used in image processing and information retrieval.\\n- Float32 vectors: Default storage with a precision of about 7 decimal digits. Even Float64 values are stored with Float32 precision, leading to potential precision loss upon retrieval.\\n- Float16 and BFloat16 vectors: Offer reduced precision and memory usage. Float16 is suitable for applications with limited bandwidth and storage, while BFloat16 balances range and efficiency, commonly used in deep learning to reduce computational requirements without significantly impacting accuracy.\\n\\n###\""
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "19998758-7f98-4cb8-8789-625fcfaad00e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'How is data stored in milvus?'"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "question"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ad25756",
   "metadata": {},
   "source": [
    "为语言模型定义系统和用户提示。此提示是使用从 Milvus 检索到的文档组装而成的。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "b655f6f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "SYSTEM_PROMPT = \"\"\"\n",
    "Human: 你是一个 AI 助手。你能够从提供的上下文段落片段中找到问题的答案。\n",
    "\"\"\"\n",
    "USER_PROMPT = f\"\"\"\n",
    "请使用以下用 <context> 标签括起来的信息片段来回答用 <question> 标签括起来的问题。最后追加原始回答的中文翻译，并用 <translated>和</translated> 标签标注。\n",
    "<context>\n",
    "{context}\n",
    "</context>\n",
    "<question>\n",
    "{question}\n",
    "</question>\n",
    "<translated>\n",
    "</translated>\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "97089c31-f85c-47a9-8498-78520513bc67",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"\\n请使用以下用 <context> 标签括起来的信息片段来回答用 <question> 标签括起来的问题。最后追加原始回答的中文翻译，并用 <translated>和</translated> 标签标注。\\n<context>\\n Where does Milvus store data?\\n\\nMilvus deals with two types of data, inserted data and metadata. \\n\\nInserted data, including vector data, scalar data, and collection-specific schema, are stored in persistent storage as incremental log. Milvus supports multiple object storage backends, including [MinIO](https://min.io/), [AWS S3](https://aws.amazon.com/s3/?nc1=h_ls), [Google Cloud Storage](https://cloud.google.com/storage?hl=en#object-storage-for-companies-of-all-sizes) (GCS), [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs), [Alibaba Cloud OSS](https://www.alibabacloud.com/product/object-storage-service), and [Tencent Cloud Object Storage](https://www.tencentcloud.com/products/cos) (COS).\\n\\nMetadata are generated within Milvus. Each Milvus module has its own metadata that are stored in etcd.\\n\\n###\\nHow does Milvus flush data?\\n\\nMilvus returns success when inserted data are loaded to the message queue. However, the data are not yet flushed to the disk. Then Milvus' data node writes the data in the message queue to persistent storage as incremental logs. If `flush()` is called, the data node is forced to write all data in the message queue to persistent storage immediately.\\n\\n###\\nHow does Milvus handle vector data types and precision?\\n\\nMilvus supports Binary, Float32, Float16, and BFloat16 vector types.\\n\\n- Binary vectors: Store binary data as sequences of 0s and 1s, used in image processing and information retrieval.\\n- Float32 vectors: Default storage with a precision of about 7 decimal digits. Even Float64 values are stored with Float32 precision, leading to potential precision loss upon retrieval.\\n- Float16 and BFloat16 vectors: Offer reduced precision and memory usage. Float16 is suitable for applications with limited bandwidth and storage, while BFloat16 balances range and efficiency, commonly used in deep learning to reduce computational requirements without significantly impacting accuracy.\\n\\n###\\n</context>\\n<question>\\nHow is data stored in milvus?\\n</question>\\n<translated>\\n</translated>\\n\""
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "USER_PROMPT"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "184b457f",
   "metadata": {},
   "source": [
    "使用 DeepSeek 提供的 `deepseek-chat` 模型根据提示生成响应。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "638a7561",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Milvus stores data in two main categories: inserted data and metadata.\n",
      "\n",
      "1. **Inserted Data** (including vector data, scalar data, and collection schemas):\n",
      "   - Stored as incremental logs in persistent storage.\n",
      "   - Supports multiple object storage backends: MinIO, AWS S3, Google Cloud Storage (GCS), Azure Blob Storage, Alibaba Cloud OSS, and Tencent Cloud COS.\n",
      "\n",
      "2. **Metadata** (generated internally by Milvus modules):\n",
      "   - Stored in etcd, a distributed key-value store.\n",
      "\n",
      "For vector data specifically, Milvus supports multiple precision types:\n",
      "- Binary (0s/1s for binary representations)\n",
      "- Float32 (default, ~7 decimal digits precision)\n",
      "- Float16/BFloat16 (reduced precision for efficiency)\n",
      "\n",
      "<translated>\n",
      "Milvus以两种主要类型存储数据：插入数据和元数据。\n",
      "\n",
      "1. **插入数据**（包括向量数据、标量数据和集合模式）：\n",
      "   - 以增量日志形式存储在持久化存储中\n",
      "   - 支持多种对象存储后端：MinIO、AWS S3、Google云存储(GCS)、Azure Blob存储、阿里云OSS和腾讯云COS\n",
      "\n",
      "2. **元数据**（由Milvus模块内部生成）：\n",
      "   - 存储在etcd分布式键值存储中\n",
      "\n",
      "对于向量数据，Milvus支持多种精度类型：\n",
      "- 二进制（0/1二进制表示）\n",
      "- Float32（默认，约7位小数精度）\n",
      "- Float16/BFloat16（降低精度以提高效率）\n",
      "</translated>\n"
     ]
    }
   ],
   "source": [
    "response = deepseek_client.chat.completions.create(\n",
    "    model=\"deepseek-chat\",\n",
    "    messages=[\n",
    "        {\"role\": \"system\", \"content\": SYSTEM_PROMPT},\n",
    "        {\"role\": \"user\", \"content\": USER_PROMPT},\n",
    "    ],\n",
    ")\n",
    "print(response.choices[0].message.content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50ce3b55-7daa-4727-95bd-3b00f6aa2b03",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
